C++ 程序设计思想基础

前言

最近发现了coursera上比较好的几门课,是来自北京大学的程序设计与算法系列课程,于是想重新回顾一下C++这门及其注重效率的语言的一些特性。同时对自己的相关知识查漏补缺,以及做一些记录。course

目录

1, 内联成员函数和缺省参数的函数
2, 构造函数

内联成员函数和缺省参数的函数

之前我们知道,内联函数存在的目的是,当一些比较简单又调用次数特别多的函数的时候,为了减少调用函数入栈时候的额外开销,我们设置一种内联函数,编译器在碰到内联函数的时候,直接把函数的代码粘过来运行。这是C++这样一种追求极致效率的语言的一种特殊机制。
那么内联成员函数的声明方法:
1, inline + 成员函数
2,整个函数体出现在类定义内部,也就是说当你把函数体写在类定义里面时,这些默认为内联函数。

1
2
3
4
5
6
class B{
inline void func1();
void func2(){};
void init(int x = 1, int y = 2);
private: int x, int y;
}

上面的func1()和func2()都是内联函数。

而缺省参数的路由是在函数的参数列表中已经给一些参数一个默认值,如之上的init()函数。那么当你调用函数的参数不够时,剩下的(靠近右边的)用默认参数。那么这种设定有什么用呢?是当你在开发较为简单的功能的时候,考虑到程序的可扩展性,即之后可能还会将某些现在是固定值的变量变成一个可控变量。则可以用到这种技术。

用重载函数和缺省参数的函数时,一定要避免函数的二义性。

构造函数

1, 一个类可以有多个构造函数。
2, 当定义了构造函数,则编译器不生成默认的无参数的构造函数(肯定会有一个构造函数)
3, 不分配内存,是在new一个对象时对这个对象进行作用。

复制构造函数

只有一个参数,即对同类对象的引用。形如X::X( X& )或者X::X(const X& )。
如果没有定义复制构造函数,那么编译器生成默认的复制构造函数。(所以当我们不写构造函数的时候,编译器会至少为我们写两个构造函数)而当你自己写了一个复制构造函数的时候,编译器就不会帮你生成复制构造函数了。

注意:
1,当初始化的时候调用 A a1 = a2;这一句是初始化语句。a1 = a2这一句是赋值语句,体会这两者的不同。
2, 当一个函数中有一个参数是类A的对象,那么当该函数被调用时,类A的复制构造函数将会被调用(对形参)。
这个时候如果你自己写了这个类的复制构造函数,那么可能这个时候实参和形参没有经历过复制工作。
3,如果函数的返回值是类A的对象时,则函数返回式,A的复制构造函数被调用。

在什么时候要自己写复制构造函数。(to be continued..)
引用作为参数时是没有生成对象的,也即不会有复制的过程,也不会调用复制构造函数。

类型转换构造函数

目的:实现类型的自动转换。
特点:只有一个参数,不是复制构造函数。
编译器自动调用->转换构造函数->建立一个临时对象。

析构函数

名字与类名相同。
前面加上~
没有返回值,没有参数,只有一个。

在对象消亡时自动被调用。用于做“善后”工作,释放内存等。

注意:对象数组的生命期结束时,每个元素的析构函数都会被调用。而对象的生命作用域是离他最近的一对花括号。当跳出作用域时,就会调用析构函数。当然,static静态对象和全局对象则在最后依次被消亡。

静态成员变量和静态成员函数

1,静态成员对象和普通成员对象的本质区别是,普通成员变量每个对象有格子的一份,而静态成员变量一共就一份,为所有对象共享。这也是sizeof不会算static变量的原因。
2,普通成员函数必须作用于某个对象,而静态成员函数并不具体作用于某个对象。
3,因此静态成员不需要通过对象就能访问。

如果访问静态成员?

不管怎么访问,但它都不属于某个特定的对象。

静态成员变量本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在;
静态成员函数本质上是全局函数;
设置静态成员这种机制的目的是将和某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。(换句话说是对全局变量分类)

注意:
1,在C++中,必须在定义类的文件中对静态成员变量进行一次说明或初始化,否则编译能通过链接不能通过。
2,在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。

成员对象和封闭类

成员对象:一个类的成员变量是另一个类的对象。
那么包含成员对象的类叫做封闭类(Enclosing).
封闭类必须要自己定义构造函数,否则就会编译报错。所以要通过初始化列表来实现。

初始化列表
类名::构造函数(参数表):成员变量1(参数表),成员变量2(参数表),…
{
}
而成员对象初始化列表中的参数.1可以是任意复杂的表达式.2函数/变量等。

当封闭类对象生成时,先执行所有成员对象的构造函数,再执行封闭类的构造函数。(顺序和成员对象在类中的说明顺序一致,和初始化列表无关。)
当封闭类对象消亡时,先执行封闭类的析构函数,再执行所有成员对象的析构函数。
析构函数顺序和构造函数的调用顺序相反

this指针

作用:指向成员函数所作用的对象。是一种特殊的指针,相当于指向一个对象入口的指针。
注意,在静态成员函数中是不能使用this指针的。

常量对象,常量成员函数

如果不希望某个对象的值被被改变,则定义该对象的时候可以再前面加const关键字。
而常量成员函数在执行期间不应该修改其所作用的对象。因此常量成员函数不能修改成员变量的值(静态成员变量除外),也不能调用同类的非常量成员函数(静态成员函数除外)。

注意:如果两个名字一样的函数一个定义了const一个没有定义,那么算是重载而不是重复定义。分别使用在const对象和非const对象上。
在引用作为参数的是很常用的,而在有些情况下,为了确保对象不会被改变可以使用常引用。